package com.szmmsoft.mp.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.szmmsoft.mp.common.constant.Constants;
import com.szmmsoft.mp.common.constant.StringPool;
import com.szmmsoft.mp.common.enums.LogStatusEnum;
import com.szmmsoft.mp.common.model.LogRecord;
import com.szmmsoft.mp.common.model.LogRequest;
import com.szmmsoft.mp.common.model.LogResponse;
import com.szmmsoft.mp.common.model.R;
import com.szmmsoft.mp.common.service.LogService;
import com.szmmsoft.mp.common.until.LoginUtil;
import com.szmmsoft.mp.model.dto.AccountLoginDTO;
import com.szmmsoft.mp.model.entity.SysLog;
import com.szmmsoft.mp.model.entity.User;
import com.szmmsoft.mp.service.SysLogService;
import com.szmmsoft.mp.mapper.SysLogMapper;
import com.szmmsoft.mp.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Map;
import java.util.Set;

/**
 * @author ethan
 * @description 针对表【sys_log(系统日志表)】的数据库操作Service实现
 * @createDate 2024-10-17 15:18:02
 */
@Service
@Slf4j
public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLog> implements SysLogService, LogService {
    @Autowired
    UserService userService;

    @Override
    public void save(LogRecord logRecord) {
        SysLog logDO = new SysLog();
        // 设置请求信息
        LogRequest logRequest = logRecord.getRequest();
        this.setRequest(logDO, logRequest);
        // 设置响应信息
        LogResponse logResponse = logRecord.getResponse();
        this.setResponse(logDO, logResponse);
        // 设置基本信息
        logDO.setDescription(logRecord.getDescription());
        logDO.setModule(StrUtil.blankToDefault(logRecord.getModule(), "").replace("API", StringPool.EMPTY));
        logDO.setTimeTaken(logRecord.getTimeTaken().toMillis());
        logDO.setCreateTime(LocalDateTime.ofInstant(logRecord.getTimestamp(), ZoneId.systemDefault()));
        // 设置操作人
        this.setCreateUser(logDO, logRequest, logResponse);
        save(logDO);
    }

    /**
     * 设置请求信息
     *
     * @param logDO      日志信息
     * @param logRequest 请求信息
     */
    private void setRequest(SysLog logDO, LogRequest logRequest) {
        logDO.setRequestMethod(logRequest.getMethod());
        logDO.setRequestUrl(logRequest.getUrl().toString());
        logDO.setRequestHeaders(JSONUtil.toJsonStr(logRequest.getHeaders()));
        logDO.setRequestBody(logRequest.getBody());
        logDO.setIp(logRequest.getIp());
        logDO.setAddress(logRequest.getAddress());
        logDO.setBrowser(logRequest.getBrowser());
        logDO.setOs(StrUtil.subBefore(logRequest.getOs(), " or", false));
    }

    /**
     * 设置响应信息
     *
     * @param logDO       日志信息
     * @param logResponse 响应信息
     */
    private void setResponse(SysLog logDO, LogResponse logResponse) {
        Map<String, String> responseHeaders = logResponse.getHeaders();
        logDO.setResponseHeaders(JSONUtil.toJsonStr(responseHeaders));
        logDO.setTraceId(MDC.get(Constants.REQ_ID));
        String responseBody = logResponse.getBody();
        logDO.setResponseBody(responseBody);
        // 状态
        Integer statusCode = logResponse.getStatus();
        logDO.setStatusCode(statusCode);
        logDO.setStatus(statusCode >= HttpStatus.HTTP_BAD_REQUEST ? LogStatusEnum.FAILURE : LogStatusEnum.SUCCESS);
        if (StrUtil.isNotBlank(responseBody)) {
            R result = JSONUtil.toBean(responseBody, R.class);
            if (!result.isOk()) {
                logDO.setStatus(LogStatusEnum.FAILURE);
                logDO.setErrorMsg(result.getMsg());
            }
        }
    }

    /**
     * 设置操作人
     *
     * @param logDO       日志信息
     * @param logRequest  请求信息
     * @param logResponse 响应信息
     */
    private void setCreateUser(SysLog logDO, LogRequest logRequest, LogResponse logResponse) {
        String requestUri = URLUtil.getPath(logDO.getRequestUrl());
        // 解析登录接口信息
        log.info("LogStatusEnum.SUCCESS.equals(logDO.getStatus())==" + LogStatusEnum.SUCCESS.equals(logDO.getStatus()));
        if (Constants.LOGIN_URI_V1.equals(requestUri) && LogStatusEnum.SUCCESS.equals(logDO.getStatus())) {
            String requestBody = logRequest.getBody();
            AccountLoginDTO loginReq = JSONUtil.toBean(requestBody, AccountLoginDTO.class);
            User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUserName, loginReq.getName()));
            logDO.setCreateUser(user.getId());
            return;
        }
        logDO.setCreateUser(LoginUtil.get());

    }
}
